package com.kaigejava.aspect;


import com.google.common.collect.Lists;
import com.kaigejava.aspect.annotates.ParamAspectAnnotate;
import com.kaigejava.dto.DataRangeBaseParamDTO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 * @author 凯哥Java
 * @description 通过AOP向threadLocal中添加参数的
 * @company 凯哥Java(http : / / www.kaigejava.com)
 * @since 2023/12/16 16:09
 */
@Aspect
@Component
public class AddParamAspect {
    //threadLocal
    private static ThreadLocal<DataRangeBaseParamDTO> dataRangeBaseParamThreadLocal = new ThreadLocal<>();


    @Pointcut("@annotation(com.kaigejava.aspect.annotates.ParamAspectAnnotate)")
    public void paramAnnotated() {
    }

    /**
     * 配置:为匹配指定表达式的方法定义切入点
     */
    @Pointcut("execution(public * com.kaigejava.controller..*.*(..))")
    public void controllerMethods() {
    }


    /**
     * 使用逻辑OR组合两个切入点
     */
    @Pointcut("paramAnnotated() || controllerMethods()")
    public void combinedPointcut() {
    }

    //设置支持注解的
    // @Before("paramAnnotated()")
    // 如果既需要支持注解也需要指定切面的。请使用这个
    @Before("combinedPointcut()")
    public void beforeParamAnnotated(JoinPoint joinPoint) {
        //优化，放到threadLocal中
        // ParamAspectAnnotate annotation = getAnnotation(joinPoint);
        //if (annotation != null) {
        DataRangeBaseParamDTO dataRangeBaseParam = new DataRangeBaseParamDTO();
        // 设置需要添加到threaLocal中的数据
        //这里模拟，添加凯哥的站点
        List<String> webSite = Lists.newArrayList();
        webSite.add("http://www.kaigejava.com");
        webSite.add("http://www.jiahaoyou.net");
        dataRangeBaseParam.setWebSite(webSite);
        //将添加的参数设置到threadLocal中
        dataRangeBaseParamThreadLocal.set(dataRangeBaseParam);
        // }

    }


    /**
     * 当方法结束是，清除掉threadLocal的数据
     *
     * @param joinPoint
     * @param result
     */
    /*@AfterReturning(pointcut = "@annotation(com.kaigejava.aspect.annotates.ParamAspectAnnotate)", returning = "result")*/
    @AfterReturning(pointcut = "paramAnnotated()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        // 在方法返回后清空 ThreadLocal 中的数据
        dataRangeBaseParamThreadLocal.remove();
    }


    /**
     * 对外提供从threadLocal获取数据的接口
     *
     * @return 从threadLocal获取到的数据
     */
    public static DataRangeBaseParamDTO getDataRangeBaseParam() {
        return dataRangeBaseParamThreadLocal.get();
    }

    /**
     * 判断方法是否有ParamAspectAnnotate注解
     *
     * @param joinPoint 切入点
     * @return ParamAspectAnnotate对象
     */
    private ParamAspectAnnotate getAnnotation(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod().getAnnotation(ParamAspectAnnotate.class);
    }
}
